package wbw.db;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Stack;

public class DbConnectPool2 {
    private String jdbcDeriver = "com.mysql.jdbc.Driver";
    private String url = "jdbc:mysql://127.0.0.1:3306/";
    private String username = "root";
    private String password = "201214600";
    private String dbname = "game";

    private Stack<Connection> freePool;
    private ArrayList<Connection> busyPool;
    private final int initCount = 10;
    private final int maxCount = 80;
    private int conCount = 0;
    private static final DbConnectPool2 dcp = new DbConnectPool2();

    public static DbConnectPool2 GetInstance() {
        return dcp;
    }

    private DbConnectPool2() {
        loadDriver();
        freePool = CreatePool();
        busyPool = new ArrayList<Connection>();
    }

    private Stack<Connection> CreatePool() {

        Stack<Connection> pool = new Stack<>();
        for (int i = 0; i < initCount; i++) {
            pool.push(createConnection());
        }
        conCount = initCount;
        return pool;
    }

    private synchronized Connection createConnection() {

        try {
            return DriverManager.getConnection(url + dbname + "?user=" + username + "&password=" + password
                    + "&useUnicode=true&characterEncoding=gbk&autoReconnect=true&failOverReadOnly=false");
        } catch (SQLException throwables) {

        }

        return null;
    }

    private void loadDriver() {
        try {
            Class.forName(jdbcDeriver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public Connection GetConnection() throws SQLException {
        if (freePool == null) {
            return null;
        }
        Connection con = getFreeConnection();
        int waitCount = 0;
        while (con == null && waitCount < 5) {
            waitCount++;
            wait(100);
            con = getFreeConnection();
        }
        return con;
    }


    private void wait(int mseconds) {
        try {
            Thread.sleep(mseconds);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    private synchronized Connection getFreeConnection() throws SQLException {
        Connection con = null;
        if (freePool.isEmpty()) {
            if (conCount < maxCount) {
                con = createConnection();
                conCount++;
                busyPool.remove(con);
            }
        } else {
            con = freePool.pop();
            if (con == null || con.isClosed()) {
                conCount--;
            } else {
                busyPool.add(con);
            }
        }
        return con;
    }

    public synchronized void FreeConnection(Connection con) throws SQLException {
        if (con == null) {
            return;

        }

        busyPool.remove(con);

        if (con.isClosed()) {
            conCount--;
        } else {
            freePool.push(con);
        }

    }
}
